// des_help
package utils

import (
	"crypto/cipher"
	"crypto/des"
	"encoding/base64"
	"fmt"
)

func DesWithKeyandIv(data, key, iv []byte) ([]byte, error) {
	return des_encypt(data, key, iv)
}

func Des_Encrypt(data, key, iv []byte) ([]byte, error) {
	return des_encypt(data, key, iv)
}

func des_encypt(data, key, iv []byte) ([]byte, error) {
	block, err := des.NewCipher(key)
	if err != nil {
		return nil, err
	}
	origData := PKCS5Padding(data, block.BlockSize())
	blockMode := cipher.NewCBCEncrypter(block, iv)

	crypted := make([]byte, len(origData))
	blockMode.CryptBlocks(crypted, origData)
	return crypted, nil
}

func Des_EncryptWithBase64(data, key []byte) (string, error) {
	res, err := des_encypt(data, key, key)
	fmt.Println(res)
	if err != nil {
		return "", err
	} else {
		return base64.StdEncoding.EncodeToString(res), nil
	}
}

func des_encyptWithBase64(data, key, iv []byte) (string, error) {
	block, err := des.NewCipher(key)
	if err != nil {
		return "", err
	}
	origData := PKCS5Padding(data, block.BlockSize())
	blockMode := cipher.NewCBCEncrypter(block, iv)

	crypted := make([]byte, len(origData))
	blockMode.CryptBlocks(crypted, origData)
	coder := base64.NewEncoding(base64Table)
	return coder.EncodeToString(crypted), nil
}

func Des_Decypt(data, key, iv []byte) ([]byte, error) {
	return des_decypt(data, key, iv)
}

func des_decypt(data, key, iv []byte) ([]byte, error) {
	block, err := des.NewCipher(key)
	if err != nil {
		return nil, err
	}
	blockMode := cipher.NewCBCDecrypter(block, key)
	origData := make([]byte, len(data))
	// origData := crypted
	blockMode.CryptBlocks(origData, data)
	origData = PKCS5UnPadding(origData)
	// origData = ZeroUnPadding(origData)
	return origData, nil
}

func Des_DecyptWithBase64(data, key, iv []byte) ([]byte, error) {
	return des_decyptWithBase64(data, key, iv)
}

func des_decyptWithBase64(data, key, iv []byte) ([]byte, error) {
	coder := base64.NewEncoding(base64Table)
	tmpdata := make([]byte, 0)
	coder.Decode(tmpdata, data)

	block, err := des.NewCipher(key)
	if err != nil {
		return nil, err
	}
	blockMode := cipher.NewCBCDecrypter(block, key)
	origData := make([]byte, len(tmpdata))
	// origData := crypted
	blockMode.CryptBlocks(origData, tmpdata)
	origData = PKCS5UnPadding(origData)
	// origData = ZeroUnPadding(origData)
	return origData, nil
}
